package com.ruoyi.service;


import cn.hutool.core.lang.Assert;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.flowable.FlowServiceFactory;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.entity.ActReDeployment;
import com.ruoyi.entity.ActReProcdef;
import com.ruoyi.mapper.ActReProcdefMapper;
import com.ruoyi.vo.FlowTaskVO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableObjectNotFoundException;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>工作流流程实例管理<p>
 *
 * @author XuanXuan
 *
 */
@Service
@Slf4j
public class FlowInstanceServiceImpl extends FlowServiceFactory {
    @Autowired
    protected ActReProcdefMapper actReProcdefMapper;

    
    public List<Task> queryListByInstanceId(String instanceId) {
        List<Task> list = taskService.createTaskQuery().processInstanceId(instanceId).active().list();
        return list;
    }

    /**
     * 结束流程实例
     *
     * @param vo
     */
    
    public void stopProcessInstance(FlowTaskVO vo) {
        String taskId = vo.getTaskId();

    }

    /**
     * 激活或挂起流程实例
     *
     * @param state      状态
     * @param instanceId 流程实例ID
     */
    
    public void updateState(Integer state, String instanceId) {

        // 激活
        if (state == 1) {
            runtimeService.activateProcessInstanceById(instanceId);
        }
        // 挂起
        if (state == 2) {
            runtimeService.suspendProcessInstanceById(instanceId);
        }
    }

    /**
     * 删除流程实例ID
     *
     * @param instanceId   流程实例ID
     * @param deleteReason 删除原因
     */
    
    @Transactional(rollbackFor = Exception.class)
    public void delete(String instanceId, String deleteReason) {

        // 查询历史数据
        HistoricProcessInstance historicProcessInstance = getHistoricProcessInstanceById(instanceId);
        if (historicProcessInstance.getEndTime() != null) {
            historyService.deleteHistoricProcessInstance(historicProcessInstance.getId());
            return;
        }
        // 删除流程实例
        runtimeService.deleteProcessInstance(instanceId, deleteReason);
        // 删除历史流程实例
        historyService.deleteHistoricProcessInstance(instanceId);
    }

    /**
     * 根据实例ID查询历史实例数据
     *
     * @param processInstanceId
     * @return
     */
    
    public HistoricProcessInstance getHistoricProcessInstanceById(String processInstanceId) {
        HistoricProcessInstance historicProcessInstance =
                historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        if (Objects.isNull(historicProcessInstance)) {
            throw new FlowableObjectNotFoundException("流程实例不存在: " + processInstanceId);
        }
        return historicProcessInstance;
    }

    /**
     * 根据流程定义ID启动流程实例
     *
     * @param procDefId 流程定义Id
     * @param variables 流程变量
     * @return
     */
    
    public AjaxResult startProcessInstanceById(String procDefId, Map<String, Object> variables) {

        try {
            // 设置流程发起人Id到流程中
            Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
//            identityService.setAuthenticatedUserId(userId.toString());
            variables.put("initiator",userId);
            variables.put("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true);
            runtimeService.startProcessInstanceById(procDefId, variables);
            return AjaxResult.success("流程启动成功");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("流程启动错误");
        }
    }
    public ProcessInstance doStart(String processDefinitionType, Long id,SysUser user, Map<String,Object> param,String candidatesUserId) {
        ActReDeployment actReDeployment = actReDeploymentMapper.getEnterpriseFlow(processDefinitionType);
        ActReProcdef actReProcdef = actReProcdefMapper.getByDeploymentId(actReDeployment.getId());
        SysDept dept = user.getDept();
        Assert.isFalse(actReProcdef == null ,"请先配置对应业务的流程图");
        String processDefinitionKey =  actReProcdef.getKey();
        Map<String,Object> variables = new HashMap<>();
        variables.put("startUserId",user.getUserId());
        variables.put("startDeptCode",dept.getOrgNo());
        variables.put("lastDeptCode",dept.getOrgNo());
        variables.put("lastAuditUserId",user.getUserId()+"");
        variables.put("candidatesUserId",candidatesUserId);
        variables.put("id",id);
        if(param != null){
            variables.putAll(param);
        }

        identityService.setAuthenticatedUserId(user.getUserId().toString());
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinitionKey).latestVersion().singleResult();

        ProcessInstanceBuilder processInstanceBuilder = runtimeService.createProcessInstanceBuilder();
        processInstanceBuilder
                .name(processDefinition.getName())
                .businessKey(processDefinitionKey + id)
                .processDefinitionId(processDefinition.getId())
                .variables(variables);
        ProcessInstance processInstance = processInstanceBuilder.start();
        return processInstance;
    }
}